package com.ideal.hadoopadmin.api.better.base;

import java.util.*;

/**
 * Created by CC on 2016/7/29.
 * 这个类用来描述一个 api的配置
 * 检查参数是否符合要求
 *
 */
public class ConfigDef {

    String name;  //定义API中的一个方法
    Map<String,ConsumerParam> params =new HashMap<String, ConsumerParam>(); //这个在配个api中被定义，是后端的操作
    Map<String,Object> vals = new HashMap<String, Object>();    //放置转换后的值



    public ConfigDef(String name){
        this.name=name;
    }

    /**
     * 配置
     * @param consumerParam
     * @return
     */
    public ConfigDef config(ConsumerParam consumerParam){
        params.put(consumerParam.getName(),consumerParam);
        return this;
    }

    public  Map<String,Object> parseParam(Map<String,Object> originalConfig){
        //把参数设置进params
        for(Map.Entry<String,Object> entry:originalConfig.entrySet()){
            if (params.containsKey(entry.getKey())){
                params.get(entry.getKey()).setVal(entry.getValue());
            }
        }

        for(Map.Entry<String,ConsumerParam> entry:params.entrySet()){
            ConsumerParam consumerParam = entry.getValue();
            if(consumerParam.getValidation()!=null&&consumerParam.getValidation().validate(consumerParam)){
                throw new ConfigException(consumerParam.getValidation().getDescription());
            }
            Object value = consumerParam.getVal();
            String name = consumerParam.getName();
            String trimmed = null;
            if (value instanceof String)
                trimmed = ((String) value).trim();
            ParamType type = consumerParam.getType();

            switch (type) {
                case BOOLEAN:
                    if (value instanceof String) {
                        if (trimmed.equalsIgnoreCase("true"))
                            vals.put(consumerParam.getName(),true);
                        else if (trimmed.equalsIgnoreCase("false"))
                            vals.put(consumerParam.getName(),false);
                        else {
                            throw new ConfigException(name, value, "Expected value to be either true or false");
                        }
                    } else if (value instanceof Boolean) {
                        vals.put(consumerParam.getName(),value);
                        break;
                    }
                    else{
                        throw new ConfigException(name, value, "Expected value to be either true or false");
                    }
                    break;
                case STRING:
                    if (value instanceof String) {
                        vals.put(consumerParam.getName(),value);
                    } else {
                        throw new ConfigException(name, value, "Expected value to be a string, but it was a " + value.getClass().getName());
                    }
                    break;
                case INT:
                    if (value instanceof Integer) {
                        vals.put(consumerParam.getName(),  (Integer) value);
                    } else if (value instanceof String) {
                        vals.put(consumerParam.getName(),  Integer.parseInt(trimmed));
                    } else {
                        throw new ConfigException(name, value, "Expected value to be an number.");
                    }
                    break;
                case SHORT:
                    if (value instanceof Short) {
                        vals.put(consumerParam.getName(), (Short) value);
                    } else if (value instanceof String) {
                        vals.put(consumerParam.getName(), Short.parseShort(trimmed));
                    } else {
                        throw new ConfigException(name, value, "Expected value to be an number.");
                    }
                    break;
                case LONG:
                    if (value instanceof Integer)
                        vals.put(consumerParam.getName(),((Integer) value).longValue());
                    if (value instanceof Long)
                        vals.put(consumerParam.getName(),(Long) value);
                    else if (value instanceof String)
                        vals.put(consumerParam.getName(), Long.parseLong(trimmed));
                    else
                        throw new ConfigException(name, value, "Expected value to be an number.");
                    break;
                case DOUBLE:
                    if (value instanceof Number)
                        vals.put(consumerParam.getName(),((Number) value).doubleValue());
                    else if (value instanceof String)
                        vals.put(consumerParam.getName(), Double.parseDouble(trimmed));
                    else
                        throw new ConfigException(name, value, "Expected value to be an number.");
                    break;
                case LIST:
                    if (value instanceof List)
                        vals.put(consumerParam.getName(), value);
                    else if (value instanceof String)
                        if (trimmed.isEmpty())
                            vals.put(consumerParam.getName(), Collections.emptyList());
                        else
                            vals.put(consumerParam.getName(), Arrays.asList(trimmed.split("\\s*,\\s*", -1)));
                    else
                        throw new ConfigException(name, value, "Expected a comma separated list.");
                    break;
                default:
                    throw new ConfigException("Unknown type.");
            }
        }
        return vals;
    }


    //这里的类型可以再扩展，最开始只用到这些个
    public enum ParamType{
        BOOLEAN,STRING,LIST,SHORT,LONG,INT,DOUBLE
    }

    //检查器
    public interface Validation {
        boolean validate(ConsumerParam param);

        String getDescription();
    }




}
